import Taro from '@tarojs/taro'
import { API_BASE_URL, API_TIMEOUT } from '@/config'

interface RequestOptions {
  url: string
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
  data?: any
  header?: Record<string, string>
  timeout?: number
  showLoading?: boolean
  loadingTitle?: string
  showError?: boolean
}

interface ResponseData<T = any> {
  code: number
  data: T
  message: string
  success: boolean
}

/**
 * HTTP请求封装
 * @param options 请求选项
 */
export async function request<T = any>(options: RequestOptions): Promise<T> {
  const {
    url,
    method = 'GET',
    data,
    header = {},
    timeout = API_TIMEOUT,
    showLoading = true,
    loadingTitle = '加载中...',
    showError = true,
  } = options

  // 显示加载提示
  if (showLoading) {
    Taro.showLoading({
      title: loadingTitle,
      mask: true,
    })
  }

  try {
    // 发起请求
    const response = await Taro.request<ResponseData<T>>({
      url: url.startsWith('http') ? url : `${API_BASE_URL}${url}`,
      method,
      data,
      header: {
        'Content-Type': 'application/json',
        ...header,
      },
      timeout,
    })

    // 请求成功，但业务状态可能失败
    const responseData = response.data

    // 业务状态判断
    if (!responseData.success) {
      const error = new Error(responseData.message || '请求失败')
      if (showError) {
        Taro.showToast({
          title: responseData.message || '请求失败',
          icon: 'none',
          duration: 2000,
        })
      }
      throw error
    }

    return responseData.data
  } catch (error: any) {
    // 请求错误处理
    if (showError && (!error.message || !error.message.includes('request:fail'))) {
      Taro.showToast({
        title: error.message || '网络异常',
        icon: 'none',
        duration: 2000,
      })
    }
    throw error
  } finally {
    // 隐藏加载提示
    if (showLoading) {
      Taro.hideLoading()
    }
  }
}

// 请求方法别名
export const get = <T = any>(url: string, data?: any, options?: Partial<RequestOptions>) =>
  request<T>({ url, method: 'GET', data, ...options })

export const post = <T = any>(url: string, data?: any, options?: Partial<RequestOptions>) =>
  request<T>({ url, method: 'POST', data, ...options })

export const put = <T = any>(url: string, data?: any, options?: Partial<RequestOptions>) =>
  request<T>({ url, method: 'PUT', data, ...options })

export const del = <T = any>(url: string, data?: any, options?: Partial<RequestOptions>) =>
  request<T>({ url, method: 'DELETE', data, ...options })
